#include <stdio.h>
#include <stdlib.h>
#include <dirent.h> 
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>
typedef struct _filename_{
    char file_name_[1024];
    struct _filename_ *next;
}FILEnameList_;
// 信号处理函数，用于捕获SIGALRM信号
void handle_sigalrm(int sig) {
    // 这里什么也不做，只是中断阻塞的waitpid调用
}
/*
0 表示成功
1 表示运行超时
3 表示运行失败
4 表示运行异常
5 表示其他错误

//该函数将运行指定可执行文件runName，并将执行结果存入outputFile中
*/
int run_out(char *runName, char *outputFile,int timeout_seconds_) {
 

    pid_t pid;
    int status;
    int out_fd;
    struct sigaction sa;

    // 设置SIGALRM信号的处理函数
    sa.sa_handler = handle_sigalrm;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    if (sigaction(SIGALRM, &sa, NULL) == -1) {
        perror("sigaction");
        return 5; // 其他错误
    }

    // 打开输出文件
    out_fd = open(outputFile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
    if (out_fd == -1) {
        perror("open");
        return 5; // 其他错误
    }

    // 创建一个子进程
    pid = fork();
    if (pid == -1) {
        perror("fork");
        close(out_fd);
        return 5; // 其他错误
    }

    if (pid == 0) {
        // 在子进程中
        // 重定向子进程的stdout到文件
        dup2(out_fd, STDOUT_FILENO);
        close(out_fd); // 关闭原来的文件描述符

        // 执行指定的可执行文件
        execl(runName, runName, NULL);

        // 如果execl调用失败，则输出错误信息并退出
        perror("execl");
        exit(EXIT_FAILURE);
    } else {
        // 在父进程中
        unsigned int timeout_seconds = timeout_seconds_; // 设置超时时间为10秒
        alarm(timeout_seconds); // 设置定时器

        // 等待子进程结束
        if (waitpid(pid, &status, 0) == -1) {
            if (errno == EINTR) {
                // 如果waitpid被SIGALRM中断，表示超时
                printf("等待子进程超时。正在终止子进程...\n");
                kill(pid, SIGKILL); // 终止子进程
                waitpid(pid, &status, 0); // 确保子进程被收割
                close(out_fd);
                return 1; // 超时
            } else {
                // 其他错误
                perror("waitpid");
                close(out_fd);
                return 5; // 其他错误
            }
        }

        // 检查子进程的退出状态
        if (WIFEXITED(status)) {
            // 子进程正常退出
            int exit_status = WEXITSTATUS(status);
            printf("子进程退出，状态为 %d\n", exit_status);
            close(out_fd);
            return exit_status == 0 ? 0 : 3; // 0表示成功，3表示运行失败
        } else if (WIFSIGNALED(status)) {
            // 子进程因信号导致异常退出
            printf("子进程因信号 %d 被终止\n", WTERMSIG(status));
            close(out_fd);
            return 4; // 运行异常
        }

        // 清除定时器（可选，因为子进程已经退出）
        alarm(0);
        close(out_fd);
    }

    // 默认情况不应该到达这里，但如果有必要，可以返回一个值
    return 5; // 其他错误
}
FILEnameList_ *ListFiles(const char* path) {  
    DIR *dir;  
    struct dirent *entry;  
    FILEnameList_ *head,*p;
    head=(FILEnameList_ *)malloc(sizeof(FILEnameList_));
    head->next=NULL;
    p=head;
    if (!(dir = opendir(path)))  
        return NULL;  
    
    while ((entry = readdir(dir)) != NULL) {  
        if (entry->d_type == DT_REG) { // 忽略目录和其他特殊文件  
            fprintf(stderr,"寻找到文件：%s\n", entry->d_name);  
            p->next=(FILEnameList_ *)malloc(sizeof(FILEnameList_));
            p->next->next=NULL;
            // strcpy(p->next->file_name_,path);
            // strcat(p->next->file_name_,"/");
            // strcat(p->next->file_name_,entry->d_name);
            strcpy(p->next->file_name_,entry->d_name);
            p=p->next;
        }  
        // fprintf(stderr,"%s\n", entry->d_name);
    }  
  
    closedir(dir);  
    return head;
} 
char *stringLink_(const char *a,const char *b)
{
    char *add=(char *)malloc(sizeof(char)*1024);
    strcpy(add,a);
    strcat(add,b);
    return add;
}
char *thefilename_add_(const char *name){
    
    if(name[strlen(name)-1]=='/')return stringLink_(name,"");
    else {
        return stringLink_(name,"/");
    }
} 

void run_allTOall(char *run_file_path,char *out_file_path){
    FILEnameList_ *fileList=ListFiles(run_file_path);
    FILEnameList_ *p=fileList->next;
    run_file_path=thefilename_add_(run_file_path);
    out_file_path=thefilename_add_(out_file_path);
    while(p){
        
        printf("开始执行文件：%s%s     ---输出结果到-->%s%s.txt\n",run_file_path,p->file_name_,out_file_path,p->file_name_);
        run_out(stringLink_(run_file_path,p->file_name_), stringLink_(out_file_path,stringLink_(p->file_name_,".txt")),10);

        p=p->next;

    }
}
void help(char *argv){
    fprintf(stderr,"该程序不进行检查错误，请确保输入正确\n");
    fprintf(stderr,"%s -r <可执行文件路径> <输出文件路径>       运行可执行文件，并将执行结果输出到输出文件\n",argv);
    fprintf(stderr,"%s -a <可执行文件夹路径> <输出文件夹路径>       遍历可执行文件夹并运行，并将执行结果输出到输出文件夹\n",argv);
}
//
int commond_(int argc, char *argv[]){
    if(argc==1){
        help(argv[0]);
    }else if(argc==2){
        if(strcmp(argv[1],"--help")==0)help(argv[0]);
        else {
            help(argv[0]);
        }
    }else if(argc==4){
        if(strcmp(argv[1],"-r")==0){
            int result = run_out(argv[1], argv[2],10);
            fprintf(stderr,"该程序运行结果：[%d]  0 表示成功 1 表示运行超时 3 表示运行失败 4 表示运行异常 5 表示其他错误\n",result);
        }else if(strcmp(argv[1],"-a")==0){
            fprintf(stderr,"执行遍历文件夹执行:\n");
            run_allTOall(argv[2],argv[3]);
        }
        // else if(strcmp(argv[1],"-r")==0){
            
        // }
    }
    

}
// int main(int argc, char *argv[]) {
//     // if (argc < 3) {
//     //     fprintf(stderr, "使用方法: %s <可执行文件路径> <输出文件路径>\n", argv[0]);
//     //     return 5; // 其他错误
//     // }

//     // int result = run_out(argv[1], argv[2]);
//     // printf("运行结果: %d\n", result);
//     commond_(argc, argv);
//     return 0;
// }
